Golang 学习笔记(五)

您所在的位置:网站首页 session archive zip中文翻译 Golang 学习笔记(五)

Golang 学习笔记(五)

2024-04-17 21:55| 来源: 网络整理| 查看: 265

archive/zip

看标准库文档,就会发现, archive/zip 和 archive/tar 看起来方法名什么的都很像。使用起来也差不多,如果是按照我的文档顺序看到的这篇文档,上一篇 tar 中已经都介绍过了,这里就不再做过多的说明。

压缩

和 tar 的过程很像,只有些小的差别,详情见示例代码。

示例代码( zip.go ):

package main import ( "archive/zip" "fmt" "io" "log" "os" "path/filepath" "strings" ) func main() { // 源档案(准备压缩的文件或目录) var src = "log" // 目标文件,压缩后的文件 var dst = "log.zip" if err := Zip(dst, src); err != nil { log.Fatalln(err) } } func Zip(dst, src string) (err error) { // 创建准备写入的文件 fw, err := os.Create(dst) defer fw.Close() if err != nil { return err } // 通过 fw 来创建 zip.Write zw := zip.NewWriter(fw) defer func() { // 检测一下是否成功关闭 if err := zw.Close(); err != nil { log.Fatalln(err) } }() // 下面来将文件写入 zw ,因为有可能会有很多个目录及文件,所以递归处理 return filepath.Walk(src, func(path string, fi os.FileInfo, errBack error) (err error) { if errBack != nil { return errBack } // 通过文件信息,创建 zip 的文件信息 fh, err := zip.FileInfoHeader(fi) if err != nil { return } // 替换文件信息中的文件名 fh.Name = strings.TrimPrefix(path, string(filepath.Separator)) // 这步开始没有加,会发现解压的时候说它不是个目录 if fi.IsDir() { fh.Name += "/" } // 写入文件信息,并返回一个 Write 结构 w, err := zw.CreateHeader(fh) if err != nil { return } // 检测,如果不是标准文件就只写入头信息,不写入文件数据到 w // 如目录,也没有数据需要写 if !fh.Mode().IsRegular() { return nil } // 打开要压缩的文件 fr, err := os.Open(path) defer fr.Close() if err != nil { return } // 将打开的文件 Copy 到 w n, err := io.Copy(w, fr) if err != nil { return } // 输出压缩的内容 fmt.Printf("成功压缩文件: %s, 共写入了 %d 个字符的数据\n", path, n) return nil }) } 解压缩

直接看代码( unzip.go )吧:

package main import ( "archive/zip" "fmt" "io" "log" "os" "path/filepath" ) func main() { // 压缩包 var src = "log.zip" // 解压后保存的位置,为空表示当前目录 var dst = "" if err := UnZip(dst, src); err != nil { log.Fatalln(err) } } func UnZip(dst, src string) (err error) { // 打开压缩文件,这个 zip 包有个方便的 ReadCloser 类型 // 这个里面有个方便的 OpenReader 函数,可以比 tar 的时候省去一个打开文件的步骤 zr, err := zip.OpenReader(src) defer zr.Close() if err != nil { return } // 如果解压后不是放在当前目录就按照保存目录去创建目录 if dst != "" { if err := os.MkdirAll(dst, 0755); err != nil { return err } } // 遍历 zr ,将文件写入到磁盘 for _, file := range zr.File { path := filepath.Join(dst, file.Name) // 如果是目录,就创建目录 if file.FileInfo().IsDir() { if err := os.MkdirAll(path, file.Mode()); err != nil { return err } // 因为是目录,跳过当前循环,因为后面都是文件的处理 continue } // 获取到 Reader fr, err := file.Open() if err != nil { return err } // 创建要写出的文件对应的 Write fw, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_TRUNC, file.Mode()) if err != nil { return err } n, err := io.Copy(fw, fr) if err != nil { return err } // 将解压的结果输出 fmt.Printf("成功解压 %s ,共写入了 %d 个字符的数据\n", path, n) // 因为是在循环中,无法使用 defer ,直接放在最后 // 不过这样也有问题,当出现 err 的时候就不会执行这个了, // 可以把它单独放在一个函数中,这里是个实验,就这样了 fw.Close() fr.Close() } return nil }

本文来自 BroQiang 博客 随意转载及使用,别忘了带上我。

本作品采用《CC 协议》,转载必须注明作者和本文链接


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3